using System;
using System.Collections.Generic;
using System.Text;

namespace AntsMap
{
    class SynthAnts
    {                     
        public double[] Eval( int dim, int elem, CostMap map, int ants, double a1, double a2, int Q, double R, double S, double q, int maxiter)
        {
            int soltotal = 0;
            double msecs = 0;
            int iters = 20;   /* sample size our measurements -- number of times we solve the problem */
            Solver solver;
            int[,] tempsol;
            int[,] bestsol;
            double avg = 0;
            double avgtime = 0;
            DateTime start;
            DateTime end;
            TimeSpan duration;

            double[] result = new double[2] {0.0,0.0};

            for( int i = 0; i < iters; i++ )
            {
                SolutionPermuter sp = new SolutionPermuter(map.Elements, map.Dimension);
                tempsol = sp.GenerateSolution();

                //solver = new SolverACO(tempsol, dim, elem, map, ants, a1,a2,Q, R,S,q, maxiter);
                solver = new SolverAnnealing(tempsol, dim, elem, map);
                start = DateTime.Now;
                while (solver.Optimal == false)
                {
                    solver.SolveStep();
                }
                end = DateTime.Now;
                duration = end - start;
                msecs += duration.TotalMilliseconds;
                soltotal += solver.BestCost();
                avg = soltotal / iters;
                avgtime = msecs / iters;
            }

            //Console.WriteLine(soltotal + " and avg is " + avg + " and time total is " + msecs + " and avg duration is " + avgtime);
            result[0] = avg;
            result[1] = avgtime;
            return result;
        }


        static void Main(string[] args)
        {
            SynthAnts synth = new SynthAnts();
            int i = 0;
            int j = 0;
            double[] result = new double[2] { 0.0, 0.0 };
            /* factor level arrays */
            /*
            double[] alpha1 = new double[3] { 0.05,0.1, 0.4 };
            double[] alpha2 = new double[3] { 0.05, 0.1, 0.7 };
            
            int[] mants = new int[3] { 5, 10, 15 };
            int[] Qlevel = new int[3] { 50, 100, 150 };
            
            int[] Rswaps = new int[3] { 1,3, 5 };
            int[] Simprove = new int[3] { 4, 5, 7 };
            
            double[] qprob = new double[3] { 0.8, 0.9, 0.95 };
            int[] iters = new int[3] { 10, 100, 200 };
            */
            
            //double[] alpha1 = new double[3] { 0.05, 0.1, 0.4 };
            double[] alpha2 = new double[4] { 0.05, 0.1, 0.15,0.2 };

            int[] mants = new int[4] { 5, 10, 15,20 };
            //int[] Qlevel = new int[3] { 50, 100, 150 };

            int[] Rswaps = new int[4] { 1, 2,3, 4 };
            //int[] Simprove = new int[3] { 4, 5, 7 };

            //double[] qprob = new double[3] { 0.8, 0.9, 0.95 };
            int[] iters = new int[4] { 50, 100,150, 200 };
            int levels = 4;

            /*
            // Parameters for the 2-level tests
            double[] alpha1 = new double[2] { 0.05, 0.1 };
            double[] alpha2 = new double[2] { 0.1, 0.4 };

            int[] mants = new int[2] { 5, 10 };
            int[] Qlevel = new int[2] { 100, 150 };

            int[] Rswaps = new int[2] { 3, 5 };
            int[] Simprove = new int[2] { 5, 7 };

            double[] qprob = new double[2] { 0.9, 0.95 };
            int[] iters = new int[2] { 100, 200 };
            int counter = 0;
            int levels = 2;
            */
/*
            // Parameters for the 4-level tests
            double[] alpha1 = new double[2] { 0.05, 0.1 };
            double[] alpha2 = new double[2] { 0.1, 0.4 };

            int[] mants = new int[2] { 5, 10 };
            int[] Qlevel = new int[2] { 100, 150 };

            int[] Rswaps = new int[2] { 3, 5 };
            int[] Simprove = new int[2] { 5, 7 };

            double[] qprob = new double[2] { 0.9, 0.95 };
            int[] iters = new int[3] { 10,100, 200 };
            int counter = 0;
            int levels = 2;
            */




            /*
             * Default parameters -- corresspond to HAS-QAP quite well
             */
            double a1 = 0.1;
            double a2 = 0.1;
            int m = 10;
            int Q = 100;
            int R = 3;
            int S = 5;
            double q = 0.9;
            int iter = 100;

            /* end factor levels */
            
            CostMap costmap;
                        
            costmap = new CostMap();
            costmap.Testfile = "testproblem-10el.txt";
            costmap.BuildCostMap();

            result = synth.Eval(costmap.Dimension, costmap.Elements, costmap, 10, 0.1, 0.1, 100, 3, 5, 0.9, 100);
            Console.WriteLine("{0}\t{1}",  result[0], result[1]);

            result = synth.Eval(costmap.Dimension, costmap.Elements, costmap, 15, 0.1, 0.1, 100, 2, 5, 0.9, 150);
            Console.WriteLine("{0}\t{1}", result[0], result[1]);

            result = synth.Eval(costmap.Dimension, costmap.Elements, costmap, 5, 0.1, 0.15, 100, 1, 5, 0.9, 150);
            Console.WriteLine("{0}\t{1}", result[0], result[1]);

/*
            for (int ii = 0; ii < 3; ii++)
            {
                //for (int j = 0; j < 3; j++)
                //{
                    result = synth.Eval(costmap.Dimension, costmap.Elements, costmap, m, a1,a2, Q, Rswaps[ii], S, q, iter);
                    Console.WriteLine("{0}\t{1}\t{2:F4}", Rswaps[ii], result[0], result[1]);  
                //}
            }
 */
            
     /*
            // for the 4 factor, 4 level tests
            for (int i1 = 0; i1 < levels; i1++)
            {
                for (int i2 = 0; i2 < levels; i2++)
                {
                    for (int i3 = 0; i3 < levels; i3++)
                    {
                        for (int i4 = 0; i4 < levels; i4++)
                        {
                            result = synth.Eval(costmap.Dimension, costmap.Elements, costmap, mants[i1], a1, alpha2[i2], Q, Rswaps[i3], S, q, iters[i4]);
                            Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}", mants[i1], alpha2[i2], Rswaps[i3], iters[i4], result[0], result[1]);
                        }
                    }
                }
            }
          */  
            
            /*
            // for the 8 factor, 2 level tests
            for (int i1 = 0; i1 < levels; i1++)
            {
                for (int i2 = 0; i2 < levels; i2++)
                {
                    for (int i3 = 0; i3 < levels; i3++)
                    {
                        for (int i4 = 0; i4 < levels; i4++)
                        {
                            for (int i5 = 0; i5 < levels; i5++)
                            {
                                for (int i6 = 0; i6 < levels; i6++)
                                {
                                    for (int i7 = 0; i7 < levels; i7++)
                                    {
                                        for (int i8 = 0; i8 < levels; i8++)
                                        {
                                            result = synth.Eval(costmap.Dimension, costmap.Elements, costmap, mants[i3], alpha1[i1], alpha2[i2], Qlevel[i4], Rswaps[i5], Simprove[i6], qprob[i7], iters[i8]);
                                            Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}", alpha1[i1], alpha2[i2], mants[i3], Qlevel[i4], Rswaps[i5], Simprove[i6], qprob[i7], iters[i8],result[0],result[1]);
                                            //Console.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7}--{8}", i1, i2, i3, i4, i5, i6, i7, i8,counter);
                                            counter++;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
     */ 
             

/*
            // -----------------------------------------------------------------------------------
            // HOLD ALL CONSTANT except
            // a1 and a2
            // ----------------------------------------------------------------------------------- 
            Console.WriteLine();
            Console.WriteLine("a1 \t a2 \t soln \t time");
            Console.WriteLine("---------------------------------------");
            for (i = 0; i < 3; i++)
            {
                for (j = 0; j < 3; j++)
                {
                    // int dim,  int elem, CostMap map, int ants, double a1, double a2, int Q, double R, double S, double q, int maxiter 
                    result = synth.Eval(costmap.Dimension, costmap.Elements, costmap, m, alpha1[i], alpha2[j], Q, R, S, q, iter);
                    //Console.WriteLine("{0}\t{1}\t{2:F4}", iters[i], result[0], result[1]);    
                    Console.WriteLine("{0} \t {1} \t {2} \t {3:F3}", alpha1[i], alpha2[j], result[0], result[1]);

                }
            }

            // -----------------------------------------------------------------------------------
            // HOLD ALL CONSTANT except
            // m and Q
            // ----------------------------------------------------------------------------------- 
            Console.WriteLine();
            Console.WriteLine("m \t Q \t soln \t time");
            Console.WriteLine("---------------------------------------");
            for (i = 0; i < 3; i++)
            {
                for (j = 0; j < 3; j++)
                {
                    // int dim,  int elem, CostMap map, int ants, double a1, double a2, int Q, double R, double S, double q, int maxiter 
                    result = synth.Eval(costmap.Dimension, costmap.Elements, costmap, mants[i], a1, a2, Qlevel[j], R, S, q, iter);
                    Console.WriteLine("{0} \t {1} \t {2} \t {3:F3}", mants[i], Qlevel[j], result[0], result[1]);

                }
            }

            
            // -----------------------------------------------------------------------------------
            // HOLD ALL CONSTANT except
            // R and S
            // ----------------------------------------------------------------------------------- 
            Console.WriteLine();
            Console.WriteLine("R \t S \t soln \t time");
            Console.WriteLine("---------------------------------------");
            for (i = 0; i < 3; i++)
            {
                for (j = 0; j < 3; j++)
                {
                    // int dim,  int elem, CostMap map, int ants, double a1, double a2, int Q, double R, double S, double q, int maxiter 
                    result = synth.Eval(costmap.Dimension, costmap.Elements, costmap, m, a1, a2, Q, Rswaps[i], Simprove[j], q, iter);
                    Console.WriteLine("{0} \t {1} \t {2} \t {3:F3}", Rswaps[i], Simprove[j], result[0], result[1]);

                }
            }



            // -----------------------------------------------------------------------------------
            // HOLD ALL CONSTANT except
            // q and iter
            // ----------------------------------------------------------------------------------- 
            Console.WriteLine();
            Console.WriteLine("q \t iters \t soln \t time");
            Console.WriteLine("---------------------------------------");
            for (i = 0; i < 3; i++)
            {
                for (j = 0; j < 3; j++)
                {
                    // int dim,  int elem, CostMap map, int ants, double a1, double a2, int Q, double R, double S, double q, int maxiter 
                    result = synth.Eval(costmap.Dimension, costmap.Elements, costmap, m, a1, a2, Q, R, S, qprob[i], iters[j]);
                    Console.WriteLine("{0} \t {1} \t {2} \t {3:F3}", qprob[i], iters[j], result[0], result[1]);

                }
            }
*/
             
        }
    }
}
